iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
自我挑戰組

Effective C++ 讀書筆記系列 第 15

[Day 15] Handle assignment to self in operator= (1)

  • 分享至 

  • xImage
  •  

前言

到了30天的中點啦!今天要介紹的是第11條守則,看來這個月結束之後可以紀錄到22條守則左右,繼續加油吧!

我們需要考慮指派給自己的情形

今天的守則跟昨天一樣,著墨於assignment operator的部分,這個守則是:

Handle assignment to self in operator=

說明的是在assignment相關操作中,需要注意到的一點是我們有時候會把objectassign 給它自己
最明顯的操作就像是這樣:

class Widget {...};

Widget w;
...
w = w;

第一反應可能是,誰會這樣寫~沒有意義!但有時候assign給自己的操作是比較隱晦一點的,例如像這樣:

a[i] = a[j]; // when i == j, assignment to itself
*px = *py; // if px and py point to the same thing, assignment to itself

是不是就蠻容易遇到的!
一般而言,我們在對於同樣類型的多個物件做操作的時候,就應該考量到它們其實同一物件的情形,甚至是不同物件類型,例如base class與derived class雖是不同類型,但它們仍可能是存放或指向同一物件!

identity test來確保self-assignment-safe

那這時要注意什麼呢?考慮以下物件:

class Bitmap {...};
class Widget 
{
private:
    Bitmap *pb;
}

以下是看似合理,但當指派給自己的時候會有問題的寫法:

Widget& Widget::operator=(const Widget& rhs)
{
    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

如果此時指派給自己,第一行pb先刪掉了,最後指派給自己,預期不會變的操作,竟然造成自己去指向一個被刪除的物件!
而要避免此情況的傳統方法就是在operator=的一開始採用 identity test
先檢查是不是指派給自己的操作:

Widget& Widget::operator=(const Widget& rhs)
{
    if(this == &rhs) return *this;
    
    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

這樣就可以避免掉self-assignment-unsafe的情形~

小結

除了identity test,還有別的作法,我們明日繼續看下去~


上一篇
[Day 14] Have assignment operators return a reference to *this
下一篇
[Day 16] Handle assignment to self in operator= (2)
系列文
Effective C++ 讀書筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言